package cn.wildfire.chat.kit.voip;

import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;

import com.bumptech.glide.Glide;
import com.sourcemuch.im.caiba.R;import com.sourcemuch.im.caiba.R2;

import org.webrtc.StatsReport;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.wildfire.chat.kit.user.UserViewModel;
import cn.wildfirechat.avenginekit.AVEngineKit;
import cn.wildfirechat.model.UserInfo;
import cn.wildfirechat.remote.ChatManager;

public class AudioFragment extends Fragment implements AVEngineKit.CallSessionCallback {
    private AVEngineKit gEngineKit;
    private boolean micEnabled = true;
    private boolean isSpeakerOn = false;

    @BindView(R2.id.portraitImageView)
    ImageView portraitImageView;
    @BindView(R2.id.nameTextView)
    TextView nameTextView;
    @BindView(R2.id.muteImageView)
    ImageView muteImageView;
    @BindView(R2.id.speakerImageView)
    ImageView spearImageView;
    @BindView(R2.id.incomingActionContainer)
    ViewGroup incomingActionContainer;
    @BindView(R2.id.outgoingActionContainer)
    ViewGroup outgoingActionContainer;
    @BindView(R2.id.descTextView)
    TextView descTextView;
    @BindView(R2.id.durationTextView)
    TextView durationTextView;

    protected boolean onCreated;

    public static VideoFragment newInstance(String targetId, boolean isOutgoing) {

        VideoFragment fragment = new VideoFragment();
        Bundle args = new Bundle();
        args.putBoolean("outgoing", isOutgoing);
        args.putString("targetId", targetId);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.av_p2p_audio_layout, container, false);
        ButterKnife.bind(this, view);
        onCreated = true;
        init();
        return view;
    }

    @Override
    public void didCallEndWithReason(AVEngineKit.CallEndReason reason) {
        // never called
    }

    @Override
    public void didChangeState(AVEngineKit.CallState state) {
        try {
            runOnUiThread(() -> {
                if (state == AVEngineKit.CallState.Connected) {
                    incomingActionContainer.setVisibility(View.GONE);
                    outgoingActionContainer.setVisibility(View.VISIBLE);
                    descTextView.setVisibility(View.GONE);
                    durationTextView.setVisibility(View.VISIBLE);
                } else {
                    // do nothing now
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void didChangeMode(boolean audioOnly) {
        // never called
    }

    @Override
    public void didCreateLocalVideoTrack() {
        // never called
    }

    @Override
    public void didReceiveRemoteVideoTrack() {
        // should never called
    }

    @Override
    public void didError(String error) {

    }


    @Override
    public void didGetStats(StatsReport[] reports) {
        runOnUiThread(() -> {
            //hudFragment.updateEncoderStatistics(reports);
            // TODO
        });
    }

    @OnClick(R2.id.muteImageView)
    public void mute() {
        try {
            AVEngineKit.CallSession session = gEngineKit.getCurrentSession();
            if (session != null && session.getState() != AVEngineKit.CallState.Idle) {
                micEnabled = !micEnabled;
                muteImageView.setSelected(micEnabled);
                session.muteAudio(micEnabled);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClick({R2.id.incomingHangupImageView, R2.id.outgoingHangupImageView})
    public void hangup() {
        try {
            AVEngineKit.CallSession session = gEngineKit.getCurrentSession();
            if (session != null) {
                session.endCall();
            } else {
                getActivity().finish();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClick(R2.id.acceptImageView)
    public void onCallConnect() {
        try {
            AVEngineKit.CallSession session = gEngineKit.getCurrentSession();
            if (session != null && session.getState() == AVEngineKit.CallState.Incoming) {
                session.answerCall(false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClick(R2.id.minimizeImageView)
    public void minimize() {
        try {
            ((SingleVoipCallActivity) getActivity()).showFloatingView();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClick(R2.id.speakerImageView)
    public void speakerClick() {
        try {
            AudioManager audioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
            int currVolume = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            if (isSpeakerOn) {
                isSpeakerOn = false;
                audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            } else {
                isSpeakerOn = true;
                audioManager.setMode(AudioManager.MODE_NORMAL);
            }
            spearImageView.setSelected(isSpeakerOn);
            audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, currVolume,
                    AudioManager.STREAM_VOICE_CALL);
            audioManager.setSpeakerphoneOn(isSpeakerOn);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 刷新语音通话信息
     */
    private void speakerUISet() {
        try {
            if (getActivity() == null) {
                return;
            }
            AudioManager audioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
            int currVolume = audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            if (isSpeakerOn) {
                audioManager.setMode(AudioManager.MODE_NORMAL);
            } else {
                audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            }
            spearImageView.setSelected(isSpeakerOn);
            audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, currVolume,
                    AudioManager.STREAM_VOICE_CALL);
            audioManager.setSpeakerphoneOn(isSpeakerOn);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void init() {
        try {
            gEngineKit = ((SingleVoipCallActivity) getActivity()).getEngineKit();
            if (gEngineKit.getCurrentSession() != null && gEngineKit.getCurrentSession().getState() == AVEngineKit.CallState.Connected) {
                descTextView.setVisibility(View.GONE);
                outgoingActionContainer.setVisibility(View.VISIBLE);
                durationTextView.setVisibility(View.VISIBLE);
            } else {
                if (((SingleVoipCallActivity) getActivity()).isOutgoing()) {
                    descTextView.setText(R.string.av_waiting);
                    outgoingActionContainer.setVisibility(View.VISIBLE);
                    incomingActionContainer.setVisibility(View.GONE);
                } else {
                    descTextView.setText(R.string.av_audio_invite);
                    outgoingActionContainer.setVisibility(View.GONE);
                    incomingActionContainer.setVisibility(View.VISIBLE);
                }
            }
            String targetId = ((SingleVoipCallActivity) getActivity()).getTargetId();
            UserInfo userInfo = ChatManager.Instance().getUserInfo(targetId, false);
            Glide.with(this).load(userInfo.portrait).into(portraitImageView);
            UserViewModel userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
            nameTextView.setText(userViewModel.getUserDisplayName(userInfo));
            muteImageView.setSelected(!micEnabled);
            isSpeakerOn = ((AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE)).isSpeakerphoneOn();
            spearImageView.setSelected(isSpeakerOn);
            updateCallDuration();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void runOnUiThread(Runnable runnable) {
        if (getActivity() != null) {
            getActivity().runOnUiThread(runnable);
        }
    }

    private Handler handler = new Handler();

    private void updateCallDuration() {
        try {
            AVEngineKit.CallSession session = gEngineKit.getCurrentSession();
            if (session != null && session.getState() == AVEngineKit.CallState.Connected) {
                long s = System.currentTimeMillis() - session.getConnectedTime();
                s = s / 1000;
                String text;
                if (s > 3600) {
                    text = String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));
                } else {
                    text = String.format("%02d:%02d", s / 60, (s % 60));
                }
                durationTextView.setText(text);
                /**
                 * 初次连接后，进入语音话筒通话
                 * */
                if (onCreated) {
                    onCreated = false;
                    isSpeakerOn = false;
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            speakerUISet();
                        }
                    }, 1000);
                }
            }
            handler.postDelayed(this::updateCallDuration, 1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
